/* Includes ------------------------------------------------------------------*/
#include "fileUpload.h"
#include <stdarg.h>
#include <string.h>
#include <stddef.h>
#include <stdio.h>
#include <errno.h>

#include "nril.h"
#include "http.h"
#include "fcntl.h"
#include "nlog.h"
/* typedef -------------------------------------------------------------------*/
/* define --------------------------------------------------------------------*/
#define FILE_UPLOAD_BOUNDARY    "AbCdEfGhIj"
/* macro ---------------------------------------------------------------------*/
/* variables -----------------------------------------------------------------*/
/* function prototypes -------------------------------------------------------*/
extern void NEDelay_Ms(int n);

/* functions -----------------------------------------------------------------*/
__attribute__((weak)) void FileUploadHook_Start(void){}
__attribute__((weak)) void FileUploadHook_End(void){}
__attribute__((weak)) int FileUploadHook_RcvHandle(char *packet ,size_t len){return 0;};

int FileUpload( char *host, 
				int port,
				char *url,
				char *path,
				int sizeOnce,
				int socketSpecified)
{
	struct sockaddr_at addrSocket;
	int length = 0, result = 0, countRead = 0, countSent = 0, countError = 0, socketId;
	int sizeFile = 0, i = 0, fileId;
	char *bufferFU = NULL, *fileName = NULL;
	struct stat fileStatus;
	
	/* fine the file name from file path */
	for(i = strlen(path); i>=0; i--)
	{	
		if(path[i] == '/' || path[i] == '\\')
		{	
			fileName = path + i + 1;	
			break;
		}
	}
	
	if(i == -1)
	{	fileName = path;	}
	
	// 
	addrSocket.sat_addr = host;
	addrSocket.sat_port = ((port == 0)? 80: port);
	
	FileUploadHook_Start();
	
	fileId = open(path, O_RDONLY);
	if(fileId < 0)
	{   
		NINFO("file open failed, code is %d\n", fileId);
		result = fileId;
		goto __end; 
	}

	fstat(fileId, &fileStatus);
	sizeFile = fileStatus.st_size;
	
	/* if socket is not specified, create a new socket */
	if(socketSpecified < 0)
	{
		socketId = socket(0, SOCK_STREAM, 0);
		if(socketId < 0)
		{	
			NWARN("socket create failed\n");
			result = socketId;
			goto __end;	
		}
	}
	else
	{	socketId = socketSpecified;	}
	
	/* alloc a pool*/
	bufferFU = (char *)malloc(sizeOnce);
	if(bufferFU == NULL)
	{
		result = -10;
		NWARN("buffer file upload alloc failed\n");
		goto __end;
	}
	if(connect(socketId, (const struct sockaddr *)&addrSocket, sizeof(struct sockaddr)) != 0)
	{	
		NWARN("connect server failed\n");
		result = -1;
		goto __end;
	}
	
	Http_Create(bufferFU, sizeOnce, "POST", host, port, url);
	Http_AddHeader(bufferFU, sizeOnce, "Content-Type: multipart/form-data; boundary="FILE_UPLOAD_BOUNDARY);
	Http_EditContent(bufferFU, sizeOnce, "--%s\r\n"
										"Content-Disposition: form-data; name=\"file\"; filename=\"%s\"\r\n"
										"Content-Type: text/plain\r\n\r\n",
										FILE_UPLOAD_BOUNDARY, 
										fileName);
	length = Http_ContentLength(bufferFU, sizeOnce);
	length += sizeFile;
	length += strlen(FILE_UPLOAD_BOUNDARY) + 4 + 4; // "\n--FILE_UPLOAD_BOUNDARY--\n"
	Http_FillContentLength(bufferFU, sizeOnce, length);
	NDEBUG("%s", bufferFU);
	result = send(socketId, bufferFU, Http_PacketLength(bufferFU, sizeOnce), 0);
  
    /* step4: loop send file data */
    while(1)
    {
        memset(bufferFU, 0, sizeOnce);
        //lseek(fileId, countSent, SEEK_SET);
        countRead = read(fileId, bufferFU, sizeOnce);
        
        if(countRead == 0)
        {   break;  }
        else if(countRead < 0)
        {   
			result = countRead;
			NWARN("read file error\n");
			goto __end; 
		}
        NDEBUG("%s", bufferFU);
		for(i=0; i<3; i++)
		{
			result = send(socketId, bufferFU, countRead, 0);
			if(result == 0)
			{	break;	}
		}
		if(i == 3)
		{	
			NWARN("send message to server error\n");
			goto __end;	
		}
        
        countSent += countRead;
    }
	
	sprintf(bufferFU, "\r\n--%s-\r\n", FILE_UPLOAD_BOUNDARY);
	NDEBUG("%s", bufferFU);
	result = send(socketId, bufferFU, strlen(bufferFU), 0);
	if(result != 0)
	{	
		NWARN("send message to server error\n");
		goto __end;	
	}
	
	NEDelay_Ms(5000);
	if((result = recv(socketId, bufferFU, 2048, 0)) > 0)
	{	
		NDEBUG("%s", bufferFU);
		result = FileUploadHook_RcvHandle(bufferFU, result);	
	}
	
__end:
	
	close(fileId);
	
	if(socketId >= 0 && socketSpecified < 0)
	{	closesocket(socketId);	}
	
	if(bufferFU != NULL)
	{	free(bufferFU);	}
	
	FileUploadHook_End();
	
	return result;
}
